﻿#include <learn/ais/ais_vector.h>

using namespace xi;
using namespace xi::ais;

AIS_Vector::AIS_Vector(std::shared_ptr<Vec3> origin, std::shared_ptr<Vec3> vector) : m_origin(origin), m_vector(vector)
{
    this->m_collisionFunc = [&](AIS_MouseMsg *msg) -> bool {
        // 获得两个屏幕点和鼠标位置（跳过开头和尾部的一段距离，以避免与所在点位置过近）
        Vec3f Q1 = msg->toScreen(convert<float>(*m_origin + *m_vector * 0.1));
        Vec3f Q2 = msg->toScreen(convert<float>(*m_origin + *m_vector * 0.9));
        Vec2f q1(Q1.x(), Q1.y());
        Vec2f q2(Q2.x(), Q2.y());
        Vec2f p = msg->move;

        // 计算投影长度
        Vec2f dir = q2 - q1;
        float len = dir.modulus();

        // 排除向量垂直于屏幕的情况
        if (len < std::numeric_limits<float>::epsilon())
            return false;

        float d = dot(p - q1, dir / len);
        float t = d / (q2 - q1).modulus();

        // 如果在范围内，直接将深度设为 0
        if (t > 0 && t < 1 && combine(q1, q2, 1 - t, t).distance(p) < 2)
        {
            msg->depth = 0;
            msg->obj = this;
            return true;
        }
        return false;
    };
}

std::shared_ptr<Vec3> AIS_Vector::vector() const
{
    return m_vector;
}

std::shared_ptr<Vec3> AIS_Vector::origin() const
{
    return m_origin;
}

void AIS_Vector::visit(AIS_InitMsg *msg)
{
    // 利用工厂创建渲染器
    if (msg->factory)
        m_renderer.reset(msg->factory->create_product("AIS_Vector"));
}

void AIS_Vector::visit(AIS_MoveMsg *msg)
{
    Vec3 n = convert<double>(msg->dir);
    Vec3 p = convert<double>(msg->pos);
    Vec3 tar = p + n * dot(n, *m_origin - p);
    Vec3 v = m_vector->normalized();
    *m_origin = *m_origin + v * dot(v, tar - *m_origin);

    // 调用父类方法更新
    AIS_Object::visit(msg);
}
